package com.ruoyi.common.utils.file;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;

import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.StringUtils;

/**
 * 图片处理工具类
 *
 * @author ruoyi
 */
public class ImageUtils
{
    private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);

    public static byte[] getImage(String imagePath)
    {
        InputStream is = getFile(imagePath);
        try
        {
            return IOUtils.toByteArray(is);
        }
        catch (Exception e)
        {
            log.error("图片加载异常 {}", e);
            return null;
        }
        finally
        {
            IOUtils.closeQuietly(is);
        }
    }

    public static InputStream getFile(String imagePath)
    {
        try
        {
            byte[] result = readFile(imagePath);
            result = Arrays.copyOf(result, result.length);
            return new ByteArrayInputStream(result);
        }
        catch (Exception e)
        {
            log.error("获取图片异常 {}", e);
        }
        return null;
    }

    /**
     * 读取文件为字节数据
     *
     * @param url 地址
     * @return 字节数据
     */
    public static byte[] readFile(String url)
    {
        InputStream in = null;
        try
        {
            if (url.startsWith("http"))
            {
                // 网络地址
                URL urlObj = new URL(url);
                URLConnection urlConnection = urlObj.openConnection();
                urlConnection.setConnectTimeout(30 * 1000);
                urlConnection.setReadTimeout(60 * 1000);
                urlConnection.setDoInput(true);
                in = urlConnection.getInputStream();
            }
            else
            {
                // 本机地址
                String localPath = RuoYiConfig.getProfile();
                String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
                in = new FileInputStream(downloadPath);
            }
            return IOUtils.toByteArray(in);
        }
        catch (Exception e)
        {
            log.error("获取文件路径异常 {}", e);
            return null;
        }
        finally
        {
            IOUtils.closeQuietly(in);
        }
    }

    /**
     * 压缩图片到指定大小
     *
     * @param data 原始图片字节数组
     * @param targetSize 目标大小（KB）
     * @param maxWidth 最大宽度
     * @param maxHeight 最大高度
     * @return 压缩后的图片字节数组
     */
    public static byte[] compressImageToSize(byte[] data, int targetSize, int maxWidth, int maxHeight) {
        try {
            // 首先读取原始图片
            BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(data));
            if (originalImage == null) {
                return data; // 如果不是有效的图片，直接返回原始数据
            }

            int originalWidth = originalImage.getWidth();
            int originalHeight = originalImage.getHeight();

            // 计算缩放后的尺寸
            int newWidth = originalWidth;
            int newHeight = originalHeight;

            // 如果图片尺寸超过指定最大尺寸，则进行缩放
            if (originalWidth > maxWidth || originalHeight > maxHeight) {
                double widthRatio = (double) maxWidth / originalWidth;
                double heightRatio = (double) maxHeight / originalHeight;
                double ratio = Math.min(widthRatio, heightRatio);

                newWidth = (int) (originalWidth * ratio);
                newHeight = (int) (originalHeight * ratio);
            }

            // 创建缩放后的图片
            Image scaledImage = originalImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
            BufferedImage bufferedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = bufferedImage.createGraphics();
            g2d.drawImage(scaledImage, 0, 0, null);
            g2d.dispose();

            // 初始压缩质量
            float quality = 0.8f;
            byte[] compressedData = compressImage(bufferedImage, quality);

            // 如果压缩后的大小还是超过目标大小，则进一步降低质量
            int targetBytes = targetSize * 1024;
            int attempts = 0;
            while (compressedData.length > targetBytes && attempts < 10) {
                quality -= 0.05f;
                if (quality <= 0.1f) {
                    quality = 0.1f;
                    break;
                }
                compressedData = compressImage(bufferedImage, quality);
                attempts++;
            }

            return compressedData;
        } catch (Exception e) {
            log.error("图片压缩异常 {}", e);
            return data; // 压缩失败时返回原始数据
        }
    }

    /**
     * 按质量压缩图片
     *
     * @param image 图片
     * @param quality 压缩质量(0-1之间，1为最高质量)
     * @return 压缩后的图片字节数组
     */
    private static byte[] compressImage(BufferedImage image, float quality) {
        try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
            // 获取JPEG图片写入器
            ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
            ImageWriteParam param = writer.getDefaultWriteParam();

            // 设置压缩质量
            param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            param.setCompressionQuality(quality);

            try (ImageOutputStream ios = ImageIO.createImageOutputStream(output)) {
                writer.setOutput(ios);
                writer.write(null, new IIOImage(image, null, null), param);
            }
            writer.dispose();

            return output.toByteArray();
        } catch (Exception e) {
            log.error("图片质量压缩异常 {}", e);
            return new byte[0];
        }
    }

    /**
     * 压缩图片（向后兼容的旧方法）
     *
     * @param data 原始图片字节数组
     * @param quality 压缩质量(0-1之间，1为最高质量)
     * @param maxWidth 最大宽度
     * @param maxHeight 最大高度
     * @return 压缩后的图片字节数组
     */
    public static byte[] compressImage(byte[] data, float quality, int maxWidth, int maxHeight) {
        return compressImageToSize(data, 500, maxWidth, maxHeight); // 默认压缩到500KB
    }
}
